package com.sqfw.project.wp.service;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sqfw.common.constant.HttpStatus;
import com.sqfw.common.exception.ServiceException;
import com.sqfw.common.utils.DateUtils;
import com.sqfw.common.utils.SecurityUtils;
import com.sqfw.common.utils.StringUtils;
import com.sqfw.common.utils.ip.IpUtils;
import com.sqfw.framework.web.domain.AjaxResult;
import com.sqfw.project.system.domain.SysDictData;
import com.sqfw.project.system.domain.SysDictType;
import com.sqfw.project.system.domain.SysUser;
import com.sqfw.project.system.mapper.SysDictDataMapper;
import com.sqfw.project.system.mapper.SysDictTypeMapper;
import com.sqfw.project.system.service.ISysDictDataService;
import com.sqfw.project.utils.AESUtils;
import com.sqfw.project.utils.HttpClientUtils;
import com.sqfw.project.utils.smgp.SMGPSmsTool;
import com.sqfw.project.wp.domain.TSmsSendLog;
import com.sqfw.project.wp.mapper.TSmsSendLogMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @description 针对表【SYS_SHORT_MSG】的数据库操作Service
 * @createDate 2023-06-12 12:18:29
 */
@Slf4j
@Service
public class TSMSSendLogService extends ServiceImpl<TSmsSendLogMapper, TSmsSendLog> implements IService<TSmsSendLog> {

    //    public static final String LOCAL_IP = "127.0.0.1";
    public static final int SM_TODAY_TOTAL = 300;

    public static final Long EXPIRE = 60 * 60 * 24 * 1L;

    /**
     * 发送短信服务apiUrl
     */
    @Value("${smgp.apiUrl}")
    private String smgpApiUrl;

    /*@Value("${smgp.phones}")
    private String phones;
    @Value("${smgp.smsContent}")
    private String smsContent;*/

    /**
     * 发送短信接口 加密的秘钥
     */
    @Value("${smgp.sqfwKey}")
    private String sqfwKey;

    private static final String SEND_MSG = "/smgp/sendMsg";

    @Autowired
    private RedisService redisService;

    @Autowired
    private ISysDictDataService dictDataService;

    @Autowired
    private SysDictTypeMapper sysDictTypeMapper;

    @Autowired
    private SysDictDataMapper sysDictDataMapper;

    /**
     * 检查当天发送的短信条数
     *
     * @param request
     * @return
     */
    public void smCheck(HttpServletRequest request, String userName) {
        String ipAddr = IpUtils.getIpAddr(request);
        String nowDay = DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, new Date());
        // 发送人ip检查 当天不能超过N条
        QueryWrapper<TSmsSendLog> msgLambdaQueryWrapper = new QueryWrapper<>();
        msgLambdaQueryWrapper
                .eq("send_ip", ipAddr)
                .apply("to_char(send_time, 'yyyy-mm-dd') = '" + nowDay + "'");
        long countIP = this.count(msgLambdaQueryWrapper);
        log.debug("IP{}在{}发送了{}条短信", ipAddr, nowDay, countIP);
        if (countIP > SM_TODAY_TOTAL) {
            throw new ServiceException(String.format("IP%s超过最大短信发送条数%d", ipAddr, SM_TODAY_TOTAL));
        }
        // 当前用户检查
        msgLambdaQueryWrapper = new QueryWrapper<>();
        msgLambdaQueryWrapper
                .eq("create_by", userName)
                .apply("to_char(send_time, 'yyyy-mm-dd') = '" + nowDay + "'");
        long countUser = this.count(msgLambdaQueryWrapper);
        log.debug("用户{}在{}发送了{}条短信", userName, nowDay, countUser);
        if (countUser > SM_TODAY_TOTAL) {
            throw new ServiceException(String.format("用户%s超过最大短信发送条数%d", userName, SM_TODAY_TOTAL));
        }
    }

    public LambdaQueryWrapper<TSmsSendLog> getListWrapper(TSmsSendLog tsmsSendLog) {
        LambdaQueryWrapper<TSmsSendLog> tsmsSendLogLambdaQueryWrapper = null;
        tsmsSendLogLambdaQueryWrapper = new LambdaQueryWrapper<>();
        tsmsSendLogLambdaQueryWrapper
                .eq(StringUtils.isNotEmpty(tsmsSendLog.getSmType()), TSmsSendLog::getSmType, tsmsSendLog.getSmType())
                .eq(StringUtils.isNotEmpty(tsmsSendLog.getReceivePhone()), TSmsSendLog::getReceivePhone, tsmsSendLog.getReceivePhone())
                .eq(StringUtils.isNotNull(tsmsSendLog.getSmNo()), TSmsSendLog::getSmNo, tsmsSendLog.getSmNo())
                .eq(StringUtils.isNotEmpty(tsmsSendLog.getWpState()), TSmsSendLog::getWpState, tsmsSendLog.getWpState())
                .like(StringUtils.isNotEmpty(tsmsSendLog.getSmContent()), TSmsSendLog::getSmContent, tsmsSendLog.getSmContent())
                .eq(StringUtils.isNotEmpty(tsmsSendLog.getStatus()), TSmsSendLog::getStatus, tsmsSendLog.getStatus());
        if (StringUtils.isNotNull(tsmsSendLog.getParams())
                && StringUtils.isNotNull(tsmsSendLog.getParams().get("beginTime"))
                && StringUtils.isNotNull(tsmsSendLog.getParams().get("endTime"))) {
            tsmsSendLogLambdaQueryWrapper.apply("to_char(send_time, 'yyyy-mm-dd hh24:mi:ss') BETWEEN '"
                    + tsmsSendLog.getParams().get("beginTime").toString() + "' and '"
                    + tsmsSendLog.getParams().get("endTime").toString() + "'");
        }
        return tsmsSendLogLambdaQueryWrapper;
    }

    public int addSmsSendLog(HttpServletRequest request, TSmsSendLog tsmsSendLog) {

        if (StringUtils.isEmpty(tsmsSendLog.getStatus())) {
            tsmsSendLog.setStatus("未传送");
        }
        tsmsSendLog.setSmNo(generateSmNo());
        SysUser sysUser = SecurityUtils.getLoginUser().getUser();
        tsmsSendLog.setSendIp(sysUser.getCode()); // 发送者工号
        this.save(tsmsSendLog);
        return 1;
    }

    public int addSmsSendLog(TSmsSendLog tsmsSendLog) {

        if (StringUtils.isEmpty(tsmsSendLog.getStatus())) {
            tsmsSendLog.setStatus("未传送");
        }
        tsmsSendLog.setSmNo(generateSmNo());
        tsmsSendLog.setCreateBy(tsmsSendLog.getReceivePhone());
        this.save(tsmsSendLog);
        return 1;
    }


    /**
     * 批量发送短信
     */
    public void sendSmsBatch(HttpServletRequest request, TSmsSendLog tSmsSendLog, String userName) {


        if (StringUtils.isEmpty(tSmsSendLog.getReceivePhones())) {
            throw new ServiceException("接收号码不能为空");
        }
        List<String> receivePhoneList = Arrays.asList(tSmsSendLog.getReceivePhones().trim().split(","));
        for (String phone : receivePhoneList) {
            if (phone.length() == 12) {
                phone = phone.substring(1);
            }
            if (!phoneCheck(phone)) {
                continue;
            }
            smCheck(request, userName);

            tSmsSendLog.setReceivePhone(phone);
            tSmsSendLog.setSmType("发");
            this.addSmsSendLog(request, tSmsSendLog);
            // 发送短信
            tSmsSendLog.setStatus("已送到");
            String result = this.sendMsgByThird(tSmsSendLog);
            if (result==null){
                tSmsSendLog.setStatus("未传送");
            }
            tSmsSendLog.setSendTime(new Date());
            this.updateById(tSmsSendLog);
        }


    }

    /**
     * 批量下发短信
     *
     * @param receivePhones 电话号码，多个用英文逗号隔开
     * @param dictLabel     短信模板字典标签，在字典里配置
     */
    public void sendSmsBatch(String receivePhones, String dictLabel) {

        if (StringUtils.isEmpty(receivePhones)) {
            throw new ServiceException("接收号码不能为空");
        }
        List<String> receivePhoneList = Arrays.asList(receivePhones.trim().split(","));
        TSmsSendLog tSmsSendLog = new TSmsSendLog();
        tSmsSendLog.setSmType("发");
        SysDictData sysDictData = dictDataService.selectDictDataByLabel(dictLabel);
        String smsContent = sysDictData.getRemark();
        // 模板特殊处理
        if ("纠错工单短信".equals(dictLabel) || "查无工单短信".equals(dictLabel)) {
            smsContent = smsContent.replaceAll("date", DateUtils.dateTimeNow("yyyy年MM月dd日"));
        }
        tSmsSendLog.setSmContent(smsContent); // 字典里配置的短信内容
        for (String phone : receivePhoneList) {
            String substring = phone.substring(0, 1);
            //手机号首位包含0，则跳过
            if ("0".equals(substring)){
                continue;
            }
            if (phone.length() == 12) {
                phone = phone.substring(1);
            }
            if (!phoneCheck(phone)) {
                continue;
            }
            tSmsSendLog.setReceivePhone(phone);
            tSmsSendLog.setCreateBy(phone);
            tSmsSendLog.setSmNo(generateSmNo());
            tSmsSendLog.setStatus("已送到");
            // 发送短信
            String result = this.sendMsgByThird(tSmsSendLog);
            if (result==null){
                tSmsSendLog.setStatus("未传送");
            }

            tSmsSendLog.setSendTime(new Date());
            this.save(tSmsSendLog);
        }

    }


    /**
     * 批量下发短信
     *
     * @param receivePhones 电话号码，多个用英文逗号隔开
     * @param dictLabel     短信模板字典标签，在字典里配置
     */
    public void sendSmsBatchOrganizedby(String receivePhones, String dictLabel, String customerName, String phoneno) {
        if (StringUtils.isEmpty(receivePhones)) {
            throw new ServiceException("接收号码不能为空");
        }
        List<String> receivePhoneList = Arrays.asList(receivePhones.trim().split(","));
        TSmsSendLog tSmsSendLog = new TSmsSendLog();
        tSmsSendLog.setSmType("发");
        SysDictData sysDictData = dictDataService.selectDictDataByLabel(dictLabel);
        String smsContentData = sysDictData.getRemark();
        String smsContent1 = "【来电人：customerName，电话：phoneno】";
        smsContent1 = smsContent1.replaceAll("customerName", StringUtils.isNotEmpty(customerName) ? customerName : "匿名");
        smsContent1 = smsContent1.replaceAll("phoneno", StringUtils.isNotEmpty(phoneno) ? phoneno : "0");
        log.info("smsContent1 : {}" , smsContent1);
        int index = smsContentData.indexOf("，");
        StringBuilder builder = new StringBuilder(smsContentData);
        StringBuilder smsContent2 = builder.insert(index, smsContent1);
        log.info("smsContent2 : {}", smsContent2.toString());
        tSmsSendLog.setSmContent(smsContent2.toString()); // 字典里配置的短信内容
        for (String phone : receivePhoneList) {
            String substring = phone.substring(0, 1);
            //手机号首位包含0，则跳过
            if ("0".equals(substring)){
                continue;
            }
            if (phone.length() == 12) {
                phone = phone.substring(1);
            }
            if (!phoneCheck(phone)) {
                continue;
            }
            tSmsSendLog.setReceivePhone(phone);
            tSmsSendLog.setCreateBy(phone);
            tSmsSendLog.setSmNo(generateSmNo());
            tSmsSendLog.setStatus("已送到");
            // 发送短信
            String result = this.sendMsgByThird(tSmsSendLog);
            if (result==null){
                tSmsSendLog.setStatus("未传送");
            }

            tSmsSendLog.setSendTime(new Date());
            this.save(tSmsSendLog);
        }

    }


    /**
     * todo 发送短信
     *
     * @param tSmsSendLog
     * @return
     */
    public String sendMsgByThird(TSmsSendLog tSmsSendLog) {

//        smgpSmsTool.sendMsg(tSmsSendLog.getReceivePhone(), tSmsSendLog.getSmContent());


        Map<String, String> headerParam = new HashMap<>(5);
        headerParam.put("token", getToken(System.currentTimeMillis(), sqfwKey));
        Map<String, String> params = new HashMap<>(16);
        // 用户号码
        params.put("receivePhone", tSmsSendLog.getReceivePhone());
        // 短信内容
        params.put("content", tSmsSendLog.getSmContent());
        log.info("发送短信参数：{}", params.toString());
        log.info("发送短信url: {}", smgpApiUrl + SEND_MSG);
        String result = HttpClientUtils.postJson(smgpApiUrl + SEND_MSG, headerParam, params, null);
        log.info("发送短信服务返回 result : {}", result);
        if (org.apache.commons.lang3.StringUtils.isBlank(result)) {
            log.info("发送短信返回-失败");
        } else {
            JSONObject resJson = JSONObject.parseObject(result);
            // 发送短信接口成功
            if (String.valueOf(HttpStatus.SUCCESS).equals(resJson.getString(AjaxResult.CODE_TAG))) {
                log.info("发送短信返回-成功");
            } else {
                log.error("发送短信错误code : {}", resJson.getString(AjaxResult.CODE_TAG));
                if (org.apache.commons.lang3.StringUtils.isNotBlank(resJson.getString(AjaxResult.MSG_TAG))) {
                    log.error("发送短信错误信息msg : {}", resJson.getString(AjaxResult.MSG_TAG));
                }
            }
        }

        return result;
    }


    private String generateSmNo() {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd");
        String date = formatter.format(System.currentTimeMillis());
        long incr = redisService.incr("SMS" + date, EXPIRE);
        String orderNumber = automaticFilling((int) incr, 6);
        String workOrderNumber = "DX" + date + orderNumber;
        return workOrderNumber;
    }

    private static String automaticFilling(int code, int num) {
        return String.format("%0" + num + "d", code);
    }


    private boolean phoneCheck(String mobile) {
        String mobileRegEx = "^1[3,4,5,6,7,8,9][0-9]{9}$";//正则表达式
        Pattern pattern = Pattern.compile(mobileRegEx);//函数语法 匹配的正则表达式
        Matcher matcher = pattern.matcher(mobile);//进行匹配
        return matcher.matches();
    }

    /**
     * 获取token, 根据时间加密：毫秒
     *
     * @param timestamp 时间戳：毫秒
     * @param key       秘钥
     * @return 加密好的token
     */
    private String getToken(Long timestamp, String key) {
        String token = AESUtils.encrypt(timestamp.toString(), key);
        return token;
    }


    /**
     * 发送固定短信
     */
    public void sendSms() {

        TSmsSendLog tSmsSendLog = new TSmsSendLog();
        tSmsSendLog.setSmType("发");
        List<SysDictData> sysDictDatas = sysDictDataMapper.selectDictDataByType("zx_outline_timeout");
        SysDictType dictType = sysDictTypeMapper.selectDictTypeByType("zx_outline_timeout");
        for (SysDictData sysDictData : sysDictDatas) {
            String phone = sysDictData.getDictLabel();
            if (StringUtils.isNotEmpty(phone)){

                if (phone.length() == 12) {
                    phone = phone.substring(1);
                }
                if (!phoneCheck(phone)) {
                    continue;
                }

                // SysDictData sysDictData = dictDataService.selectDictDataByLabel(dictLabel);
                // String smsContent = sysDictData.getRemark();
                tSmsSendLog.setSmContent(dictType.getRemark()); // 配置文件的短信内容
                tSmsSendLog.setReceivePhone(phone);
                tSmsSendLog.setCreateBy(phone);
                tSmsSendLog.setSmNo(generateSmNo());
                tSmsSendLog.setStatus("已送到");
                // 发送短信

                String result = this.sendMsgByThird(tSmsSendLog);
                if (result == null) {
                    tSmsSendLog.setStatus("未传送");
                }

                tSmsSendLog.setSendTime(new Date());
                this.save(tSmsSendLog);


            }
        }


    }
}
